package de.dhbw.karlsruhe.picsim.model.timer;

import de.dhbw.karlsruhe.picsim.model.cpu.ReadOnlyFile;

/**
 * Created by IntelliJ IDEA.
 * User: goesen
 * Date: Apr 28, 2010
 * Time: 7:05:25 PM
 */

/**
 * 1.
 * Wenn der Prescaler überläuft, überprüfe ob er dem Timer0 zugewiesen ist: wenn ja erhöhe Timer0 ansonsten tue nichts
 * 2.
 * Wenn eine (wie auch immer geartete Zeit Einheit verstreicht) überprüfe wieder ob der prescaler dem Timer0 zugewisen
 * ist: wenn Ja erhöhe den Prescaler ansonsten erhöhe den Timer0
 */
final class Timer0Control implements Timer {
    private final ReadOnlyFile option;
    private final Timer timer0;
    private final ObservableTimer preScaler;

    Timer0Control(final ReadOnlyFile option, final ObservableTimer preScaler, final Timer timer0) {
        this.option = option;
        this.preScaler = preScaler;
        this.timer0 = timer0;
        preScaler.addTimeoutListener(new ObservableTimer.TimeoutListener() {
            @Override
            public void timeoutOccurred() {
                if (isPreScalerAssignedToTimer(option)) {
                    timer0.increment();
                }

            }
        });
    }

    /**
     * wird aufgerufen wenn ein circle oder ein externes clock event generiert wird
     */
    @Override
    public void increment() {
        /*  P25
         The prescaler is shared between the Timer0 Module
        and the Watchdog Timer. The prescaler assignment is
        controlled, in software, by control bit PSA
        (OPTION<3>). Clearing bit PSA will assign the
        prescaler to the Timer0 Module. 
        */
        if (isPreScalerAssignedToTimer(option)) {
            preScaler.increment();
        } else {
            timer0.increment();
        }

    }

    static boolean isPreScalerAssignedToTimer(final ReadOnlyFile option) {
        return !option.getData().isSet(3);
    }

}
